<template>
  <div class="uploader">
    <slot :files="files" :file-list="fileList" :started="started">
      <uploader-unsupport />
      <uploader-drop :single-flag="singleFlag" />
      <uploader-list v-show="showListFlag" />
    </slot>
  </div>
</template>

<script>
import Uploader from 'simple-uploader.js'
import { kebabCase } from './common/utils'
import UploaderDrop from './components/drop.vue'
import UploaderUnsupport from './components/unsupport.vue'
import UploaderList from './components/list.vue'

const FILE_ADDED_EVENT = 'fileAdded'
const FILES_ADDED_EVENT = 'filesAdded'
const UPLOAD_START_EVENT = 'uploadStart'

export default {
  components: {
    UploaderDrop,
    UploaderUnsupport,
    UploaderList
  },
  provide() {
    return {
      uploader: this,
      fileDownload: this.fileDownload,
      fileDelete: this.fileDelete
    }
  },
  props: {
    options: {
      type: Object,
      default() {
        return {}
      }
    },
    singleFlag: {
      type: Boolean,
      default: false
    },
    // 是否自动开始上传
    autoStart: {
      type: Boolean,
      default: true
    },
    // 是否显示文件列表
    showListFlag: {
      type: Boolean,
      default: true
    },
    fileStatusText: {
      type: [Object, Function],
      default() {
        return {
          success: 'success',
          error: 'error',
          uploading: 'uploading',
          paused: 'paused',
          waiting: 'waiting'
        }
      }
    },
    showSuccessFiles: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      started: false,
      files: [],
      fileList: []
    }
  },
  beforeUpdate() {
    // this.options.initialPaused = !this.autoStart
    this.uploader.opts.query = this.options.query
  },
  created() {
    this.options.initialPaused = !this.autoStart
    const defaultOptions = {
      // 默认块大小是10M
      chunkSize: 10485760
    }
    const opts = Object.assign(defaultOptions, this.options)
    const uploader = new Uploader(opts)
    this.uploader = uploader
    this.uploader.fileStatusText = this.fileStatusText
    uploader.on('catchAll', this.allEvent)
    uploader.on(FILE_ADDED_EVENT, this.fileAdded)
    uploader.on(FILES_ADDED_EVENT, this.filesAdded)
    uploader.on('fileRemoved', this.fileRemoved)
    uploader.on('filesSubmitted', this.filesSubmitted)
  },
  destroyed() {
    const uploader = this.uploader
    uploader.off('catchAll', this.allEvent)
    uploader.off(FILE_ADDED_EVENT, this.fileAdded)
    uploader.off(FILES_ADDED_EVENT, this.filesAdded)
    uploader.off('fileRemoved', this.fileRemoved)
    uploader.off('filesSubmitted', this.filesSubmitted)
    this.uploader = null
  },
  methods: {
    fileDownload(file) {
      this.$emit('file-download', file)
    },
    fileDelete(file) {
      this.$emit('file-delete', file)
    },
    uploadStart() {
      this.started = true
    },
    fileAdded(file) {
      this.$emit(kebabCase(FILE_ADDED_EVENT), file)
      if (file.ignored) {
        // is ignored, filter it
        return false
      }
    },
    filesAdded(files, fileList) {
      this.$emit(kebabCase(FILES_ADDED_EVENT), files, fileList)
      if (files.ignored || fileList.ignored) {
        // is ignored, filter it
        return false
      }
    },
    fileRemoved(file) {
      this.files = this.uploader.files
      this.fileList = this.uploader.fileList
    },
    filesSubmitted(files, fileList) {
      this.files = this.uploader.files
      this.fileList = this.uploader.fileList
      if (this.autoStart) {
        this.uploader.upload()
      }
    },
    allEvent(...args) {
      const name = args[0]
      const EVENTSMAP = {
        [FILE_ADDED_EVENT]: true,
        [FILES_ADDED_EVENT]: true,
        [UPLOAD_START_EVENT]: 'uploadStart'
      }
      const handler = EVENTSMAP[name]
      if (handler) {
        if (handler === true) {
          return
        }
        this[handler].apply(this, args.slice(1))
      }
      args[0] = kebabCase(name)
      this.$emit.apply(this, args)
    }

  }
}
</script>

<style lang="scss" scoped>
.uploader {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  &:hover {
    border-color: #1890ff;
  }
}
</style>
